package controller;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import data.dao.LeaveDAOException;
import data.dao.UserDAOException;
import data.dao.daoImplementation.NotFoundException;
import data.dto.CompensationConsumedDTO;
import data.dto.CompensationLeaveUserDetails;
import data.dto.HolidaysDTO;
import data.dto.LeaveDTO;
import data.dto.UserDTO;
import data.dto.userTypeDTO;
import data.searchdto.CompensationConsumedSearchDTO;
import data.searchdto.HolidaySearchDTO;
import data.searchdto.LeaveSearchDTO;
import data.searchdto.UserSearchDTO;
import data.searchdto.UserTypeSearchDTO;
import manager.LeaveManager;
import manager.LeaveTypeManager;
import manager.UserManager;

/**
 * Servlet implementation class StaffLeaveApplyServlet
 */
// @WebServlet(description = "Staff Leave Application", urlPatterns = {
// "/StaffLeaveApplyServlet" }, loadOnStartup = 1)
@WebServlet("/StaffLeaveApplyServlet")
public class StaffLeaveApplyServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	public UserManager userMgr = new UserManager();
	public LeaveManager leaveMgr = new LeaveManager();
	public LeaveTypeManager leaveTypeMgr = new LeaveTypeManager();

	/**
	 * @see HttpServlet#HttpServlet()
	 */
	public StaffLeaveApplyServlet() {
		super();
		// TODO Auto-generated constructor stub
	}

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		try {
			doProcess(request, response);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (UserDAOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (data.dao.daoImplementation.SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		try {
			doProcess(request, response);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (UserDAOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (data.dao.daoImplementation.SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	private void doProcess(HttpServletRequest request,
			HttpServletResponse response) throws SQLException,
			NotFoundException, UserDAOException,
			data.dao.daoImplementation.SQLException {
		try {
			request.setAttribute("title", "Apply Leave");

			String page = "";
			UserDTO user = util.CurrentUser.getCurrentUser(request.getSession());

			// check user
			if (user == null) {
				page = util.Constants.homePage;
			} else if (util.CurrentUser.isAdmin(user)) {
				page = util.Constants.homePage;
			} else {

				page = "/ManagePersonalLeaveServlet";

				String check = request.getParameter("ins") == null ? ""
						: request.getParameter("ins");

				if (check.isEmpty()) {
					page = "/staff/applyLeave.jsp?apply=true";

					LeaveTypeManager ltm = new LeaveTypeManager();
					request.setAttribute("leaveTypes",
							ltm.findAllLeaveTypeDisplay());
					request.setAttribute("natureOfLeaves",
							ltm.findAllNatureOfLeaveDisplay());
				} else {

					// Setting Data from JSP
					float converttoday = 0f;
					float days = 0f;
					String leaveType = request.getParameter("leaveType") == "0" ? ""
							: request.getParameter("leaveType");
					String natureOfLeave = request
							.getParameter("natureOfLeave") == "0" ? ""
							: request.getParameter("natureOfLeave");
					String reason = request.getParameter("reason") == null ? ""
							: request.getParameter("reason").trim();
					String workDisemmination = request
							.getParameter("workDisemmination") == null ? ""
							: request.getParameter("workDisemmination").trim();
					String contactDetails = request
							.getParameter("contactDetails") == null ? ""
							: request.getParameter("contactDetails").trim();

					String sDateSt, eDateSt;
					SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
					Date sDate = null;
					Date eDate = null;

					Timestamp timeStampSDate, timeStampEDate;
					Boolean dateFlag = true, leaveTypeFlag = true, overtimeFlag = true, datecompareFlag = true, isError = true;

					// calculate StartDate and EndDate
					sDateSt = request.getParameter("startDate") == "" ? "2011-12-01 00:00:00"
							: request.getParameter("startDate");
					eDateSt = request.getParameter("endDate") == "" ? "2011-12-01 00:00:00"
							: request.getParameter("endDate");
					sDate = df.parse(sDateSt);
					eDate = df.parse(eDateSt);
					timeStampSDate = new Timestamp(sDate.getTime());
					timeStampEDate = new Timestamp(eDate.getTime());

					LeaveDTO leave = new LeaveDTO();
					CompensationConsumedDTO compensate = new CompensationConsumedDTO();

					// Insert into user table

					int userId = util.CurrentUser.getCurrentUser(
							request.getSession()).getId();
					// .getId();
					// short userId=1;
					UserSearchDTO userSearchDto = new UserSearchDTO(
							(short) userId, null, "", 0, 0);
					user = userMgr.findUser(userSearchDto);

					UserTypeSearchDTO userTypeSearchDto = new UserTypeSearchDTO(
							user.getId(), null);

					userTypeDTO usertype = userMgr
							.findUserType(userTypeSearchDto);

					// Short userTypeId=usertype.getId();
					// Short annual = usertype.getAnnualLeave();
					// Short medical = usertype.getMedicalLeave();
					// float compensation = usertype.getCompensationLeave();

					Short annual = leaveMgr.findremainingleave(user.getId(),
							(short) 1, user.getUserType());
					Short medical = leaveMgr.findremainingleave(user.getId(),
							(short) 2, user.getUserType());
					float compensation = (float) leaveMgr.findremainingleave(
							user.getId(), (short) 3, user.getUserType());

					usertype.setId(usertype.getId());
					usertype.setName(usertype.getName());
					usertype.setAnnualLeave(annual);
					usertype.setMedicalLeave(medical);
					usertype.setCompensationLeave(compensation);

					LeaveManager LM = new LeaveManager();
					HolidaySearchDTO search = new HolidaySearchDTO(null,
							timeStampSDate, timeStampEDate);
					ArrayList<HolidaysDTO> list = LM.findHoiliday(search);

					// Setting overtime to UserDTO
					String overTimeErrMsg;
					if (request.getParameter("overTime") != ""
							&& Short.parseShort(leaveType) == 3) {
						days = Float.parseFloat(request
								.getParameter("overTime"));

						if (user.getOverTime() != 0 && days >= 0.5) {
							days = (float) (days + (user.getOverTime()));
							user.setOverTime((short) (days));
						} else if (user.getOverTime() == 0 && days >= 0.5) {
							user.setOverTime((short) (days));
						} else {
							overtimeFlag = false;
						}

						if (!list.equals(null) && days > 0) {
							if (days <= 14f)
								days = days - list.size();
						}
					}

					int totalDay = 0;
					String leaveErrorMsg = new String("Total leave day is applied is more than remaining");	
					if (overtimeFlag == true) {

						// calculate total leave day
						//long diffDays = eDate.getTime() - sDate.getTime();
						totalDay = (int)( (eDate.getTime() - sDate.getTime()) / (1000 * 60 * 60 * 24));
						//totalDay = (int) diffDays / (24 * 60 * 60 * 1000);
						totalDay++;

						// checking startDate and today
						Date todayDate = df.parse(util.CurrentDate
								.getCurrentDate());
						if (sDate.compareTo(todayDate) < 0) {
							datecompareFlag = false;
						}

						if (1 == Short.parseShort(request
								.getParameter("leaveType"))) {
							if (annual < totalDay) {
								// show error page
								leaveErrorMsg = "Number of annual leaves applied ("+annual+") is more than remaining ("+totalDay+")";
								leaveTypeFlag = false;
							} else {
								annual = (short) (annual - totalDay);
							}
						} else if (2 == Short.parseShort(request
								.getParameter("leaveType"))) {
							if (medical < totalDay) {
								// show error page
								leaveErrorMsg = "Number of medical leaves applied ("+medical+") is more than remaining ("+totalDay+")";
								leaveTypeFlag = false;
							} else {
								medical = (short) (medical - totalDay);
							}

						}
						// else if (3 ==
						// Short.parseShort(request.getParameter("leaveType")))
						// {
						// if (compensation < totalDay) {
						// // show error page
						// leaveErrorMsg =
						// "Total leave day is more than medical leave";
						// leaveTypeFlag = false;
						// } else {
						// compensation = (short) (compensation - totalDay);
						// }
						// }

						if (!list.equals(null) && totalDay > 0) {
							if (totalDay <= 14)
								totalDay = totalDay - list.size();
						}
					}
					boolean isLoad=true;
					if (totalDay < 0)
						dateFlag = false;

					if (!dateFlag) {
						request.setAttribute("dateErrMsg",
								"Start Date Should Be Earlier Than End Date");
						isError = false;
					}
					if (!leaveTypeFlag) {
						request.setAttribute("leaveTypeErrMsg",	leaveErrorMsg);
						isError = false;
					}
					if (!overtimeFlag) {
						request.setAttribute("overTimeErrMsg",
								"You can not have compensation. You don't have enough overtime");
						isError = false;
					}
					if (!datecompareFlag) {
						request.setAttribute("dateCompareErrMsg",
								"Start Date should initialize from today");
						isError = false;
					}
					if (!isError) {
						check = request.getParameter("ins") == null ? ""
								: request.getParameter("ins");
						if (check.isEmpty()) {
							page = "/staff/applyLeave.jsp?apply=true";
						}
						else
						{
							page = "/staff/applyLeave.jsp?update=true";
						}
					} else {
						check = request.getParameter("ins");
						if (check.equalsIgnoreCase("true")) {

							// Insert into LeaveDTO
							leave.setLeaveType(Short.parseShort(leaveType));
							leave.setStartDate(timeStampSDate);
							leave.setEndDate(timeStampEDate);
							leave.setNatureOfLeave(Short
									.parseShort(natureOfLeave));
							leave.setReason(reason);
							leave.setWorkDisemmination(workDisemmination);
							leave.setContactDetails(contactDetails);
							leave.setStatus(util.Constants.LEAVE_APPLICATION_STATUS_APPLIED);

							leaveMgr.insertLeaveDetail(leave,
									request.getSession());
							userMgr.updateLeaveDetail(user);
							userMgr.updateUserType(usertype);
							if (Integer.parseInt(leaveType) == 3) {
								compensate.setNumberofdays((float) days);
								compensate.setUserid((int) userId);
								leaveTypeMgr
										.insertCompensationLeave(compensate);
							}

						} else {

							int leaveId = Integer.parseInt(request
									.getParameter("id"));

							// update into LeaveDTO
							leave.setId(leaveId);
							leave.setLeaveType(Short.parseShort(leaveType));
							leave.setStartDate(timeStampSDate);
							leave.setEndDate(timeStampEDate);
							leave.setNatureOfLeave(Short
									.parseShort(natureOfLeave));
							leave.setReason(reason);
							leave.setWorkDisemmination(workDisemmination);
							leave.setContactDetails(contactDetails);
							leave.setStatus(util.Constants.LEAVE_APPLICATION_STATUS_UPDATED);

							leaveMgr.updateLeaveDetail(leave);
							userMgr.updateLeaveDetail(user);
							userMgr.updateUserType(usertype);

							if (Integer.parseInt(leaveType) == 3) {
								compensate.setUserid((int) userId);
								ArrayList<CompensationConsumedDTO> compensateDTO = leaveTypeMgr
										.findCompensationDetailByID(compensate);
								int compensateId = compensateDTO.get(0).getId();
								compensate.setId(compensateId);
								compensate.setUserid((int) userId);
								compensate.setNumberofdays((float) days);
								leaveTypeMgr
										.updateCompensationLeave(compensate);
							}
						}

						ArrayList<LeaveDTO> leavedata = leaveMgr.findAllLeave();
						request.setAttribute("leave", leavedata);
						page = "/ManagePersonalLeaveServlet";
					}
					
				}
				RequestDispatcher rd = request
						.getRequestDispatcher(page);
				rd.forward(request, response);
			}

		} catch (LeaveDAOException e) {
			e.printStackTrace();
		} catch (ParseException e) {
			e.printStackTrace();
		} catch (ServletException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
